package main

import (
	"fmt"
	"go-xorm-01/utils"
	"time"
	"xorm.io/xorm"
	"xorm.io/xorm/log"
	"xorm.io/xorm/names"
)

var engine *xorm.Engine

// 事件:https://xorm.io/zh/docs/chapter-12/readme/
// xorm 支持两种方式的事件，一种是在 Struct中的特定方法来作为事件的方法，一种是在执行语句的过程中执行事件。
//
// 在Struct中作为成员方法的事件如下：
//
// BeforeInsert()
// 在将此struct插入到数据库之前执行
//
// BeforeUpdate()
// 在将此struct更新到数据库之前执行
//
// BeforeDelete()
// 在将此struct对应的条件数据从数据库删除之前执行
//
// func BeforeSet(name string, cell xorm.Cell)
// 在 Get 或 Find 方法中，当数据已经从数据库查询出来，而在设置到结构体之前调用，name为数据库字段名称，cell为数据库中的字段值。
//
// func AfterSet(name string, cell xorm.Cell)
// 在 Get 或 Find 方法中，当数据已经从数据库查询出来，而在设置到结构体之后调用，name为数据库字段名称，cell为数据库中的字段值。
//
// AfterLoad()
// 在 Get 或 Find 方法中，当数据已经从数据库查询出来，而在设置到结构体之后调用。
//
// AfterLoad(*xorm.Session)
// 在 Get 或 Find 方法中，当数据已经从数据库查询出来，而在设置到结构体之后调用，并传递xorm.Session参数。
//
// AfterInsert()
// 在将此struct成功插入到数据库之后执行
//
// AfterUpdate()
// 在将此struct成功更新到数据库之后执行
//
// AfterDelete()
// 在将此struct对应的条件数据成功从数据库删除之后执行
//
// 在语句执行过程中的事件方法为：
//
// Before(beforeFunc interface{})
func main() {
	SnakeMapper()
	//insetManyUser(engine)
	//engine.DumpAllToFile("demo05-query/demo01-querywhere/sql.sql")
	envent(engine)
}

func envent(engine *xorm.Engine) {
	//var userInsert UserQuery = UserQuery{
	//	Username: "insert-test",
	//	Password: "123456",
	//	GroupId:  1,
	//	Rank:     1,
	//}
	//engine.Insert(&userInsert)

	var userQ UserQuery
	before := func(bean interface{}) {
		fmt.Println("BeforeQ....", bean)
	}
	engine.Before(before).ID(3).Get(&userQ)
	fmt.Println("userQ=", userQ)

}

func SnakeMapper() {
	engine = utils.GenerateEngine()
	engine.SetMapper(names.SnakeMapper{}) // SnakeMapper 【默认】
	err := engine.Sync2(new(UserQuery))
	if err != nil {
		fmt.Printf("err:%v", err)
	}
	engine.ShowSQL(true)
	engine.SetLogLevel(log.LOG_DEBUG)

}

func insetManyUser(engine *xorm.Engine) {
	groupOne := make([]*UserQuery, 0)
	for i := 0; i < 5; i++ {
		groupOne = append(groupOne, &UserQuery{
			Username: fmt.Sprintf("zhangsan-%d", i),
			Password: fmt.Sprintf("123456-%d", i),
			GroupId:  1,
			Rank:     i,
		})
	}
	engine.Insert(groupOne)

	groupTwo := make([]*UserQuery, 0)
	for i := 0; i < 3; i++ {
		groupTwo = append(groupTwo, &UserQuery{
			Username: fmt.Sprintf("lisi-%d", i),
			Password: fmt.Sprintf("00000-%d", i),
			GroupId:  2,
			Rank:     i,
		})
	}
	engine.Insert(groupTwo)

}

type JsonTime time.Time

func (j JsonTime) MarshalJSON() ([]byte, error) {
	return []byte(`"` + time.Time(j).Format("2006-01-02 15:04:05") + `"`), nil
}

type UserQuery struct {
	Id        int64     `xorm:"pk autoincr"`                                              //指定列名 ，默认id
	Username  string    `xorm:"varchar(25) notnull unique(u_p) 'username' comment('姓名')"` //复合唯一索引
	Password  string    `xorm:"varchar(25) notnull unique(u_p) 'password' comment('密码')"` //复合唯一索引
	TimeOne   time.Time `xorm:"created"`
	TimeTwo   JsonTime  `xorm:"created"`
	TimeThree int64     `xorm:"created"`
	GroupId   int64
	Rank      int
}

func (user UserQuery) BeforeInsert() {
	fmt.Println("BeforeInsert....")

}
